///////////////////////////////////////////////////////////////////////////////
// svec.cpp
// Author: Nick Leaf
// Last Updated: 9/2009
//
// Description: Implementation for the svec class.  See svec.h.
///////////////////////////////////////////////////////////////////////////////

#include "svec.h"
#include <sstream>
#include <math.h>
#include "cvec.h"

//////////////////////////////////////////////////
///////// Constructors ///////////////////////////
svec::svec(float r, float theta, float phi){
    v[0] = r;
    v[1] = theta;
    v[2] = phi;
}

svec::svec(float *arr){
    v[0] = arr[0];
    v[1] = arr[1];
    v[2] = arr[2];
}
//////////////////////////////////////////////////





//////////////////////////////////////////////////
////////// Accessors /////////////////////////////
float svec::r() const{return v[0];}
float svec::theta() const{return v[1];}
float svec::phi() const{return v[2];}

float *svec::toArray() const{
    float *v = new float[3];
    v[0] = this->v[0];
    v[1] = this->v[1];
    v[2] = this->v[2];

    return v;
}

std::string svec::toString() const{
    std::stringstream gstring;
    gstring << *this;
    return gstring.str();
}
//////////////////////////////////////////////////





//////////////////////////////////////////////////
////////// Mutators //////////////////////////////
void svec::r(float r) {v[0] = r;}
void svec::theta(float theta) {v[1] = theta;}
void svec::phi(float phi) {v[2] = phi;}
//////////////////////////////////////////////////





//////////////////////////////////////////////////
////////// Coordinate conversion /////////////////
cvec svec::toCartesian() const{
    return cvec(r() * sin(theta()) * cos(phi()),
            r() * cos(theta()),
            r() * sin(theta()) * sin(phi()));
}
//////////////////////////////////////////////////





//////////////////////////////////////////////////
////////// Vector operations /////////////////////
float svec::mag() const{ return v[0]; }
svec svec::mulByScalar(float f) const{ return svec(v[0]*f, v[1], v[2]); }
svec svec::divByScalar(float f) const{ 
    if(f!=0) return svec(v[0]/f, v[1], v[2]); 
    else return svec();
}

svec svec::norm() const{ return divByScalar(mag()); }
//////////////////////////////////////////////////





//////////////////////////////////////////////////
////////// Overloaded operators //////////////////

//access operators
svec::operator float* (){ return v; }
float &svec::operator [] (int i){ return v[i]; }

//scalar arithmetic
svec operator* (float f, svec v){ return v.mulByScalar(f); }
svec operator* (svec v, float f){ return v.mulByScalar(f); }

svec svec::operator/ (float f) const{ return (*this).divByScalar(f); }

std::ostream& operator<< (std::ostream &out, const svec &v){
    return out << "[" << v.r() << " " << v.theta() << " " << v.phi() << "]";
}

std::istream& operator>> (std::istream &in, svec &v){
    char inc;

    //expects format "[r<delim>theta<delim>phi]"
    in >> inc >> v[0] >> inc >> v[1] >> inc >> v[2] >> inc;

    return in;
}
//////////////////////////////////////////////////
